using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using log4net;
using Triton.Common;
using Triton.Common.LogUtilities;

namespace Triton.Bot
{
	public static class PluginManager
	{
		public delegate void PluginEvent(IPlugin plugin);

		[Serializable]
		[CompilerGenerated]
		private sealed class Class206
		{
			public static readonly Class206 Instance9 = new Class206();

			public static Func<IPlugin, bool> Instance9__45_0;

			public static Func<IPlugin, bool> Instance9__47_0;

			internal bool method_0(IPlugin iplugin_0)
			{
				return iplugin_0.IsEnabled;
			}

			internal bool method_1(IPlugin iplugin_0)
			{
				return !iplugin_0.IsEnabled;
			}
		}

		private static readonly ILog ilog_0 = Logger.GetLoggerInstanceForType();

		[CompilerGenerated]
		private static List<IPlugin> list_0;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_0;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_1;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_2;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_3;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_4;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_5;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_6;

		[CompilerGenerated]
		private static PluginEvent pluginEvent_7;

		public static List<IPlugin> Plugins
		{
			[CompilerGenerated]
			get
			{
				return list_0;
			}
			[CompilerGenerated]
			private set
			{
				list_0 = value;
			}
		}

		private static string String_0 => Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

		public static string PluginsPath => Path.Combine(String_0, "Plugins");

		public static IEnumerable<IPlugin> EnabledPlugins => Plugins.Where((IPlugin iplugin_0) => iplugin_0.IsEnabled);

		public static IEnumerable<IPlugin> DisabledPlugins => Plugins.Where((IPlugin iplugin_0) => !iplugin_0.IsEnabled);

		public static event PluginEvent PreStart
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_0;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_0, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_0;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_0, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static event PluginEvent PostStart
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_1;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_1, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_1;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_1, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static event PluginEvent PreTick
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_2;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_2, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_2;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_2, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static event PluginEvent PostTick
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_3;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_3, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_3;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_3, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static event PluginEvent PreStop
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_4;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_4, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_4;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_4, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static event PluginEvent PostStop
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_5;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_5, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_5;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_5, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static event PluginEvent PluginEnabled
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_6;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_6, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_6;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_6, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static event PluginEvent PluginDisabled
		{
			[CompilerGenerated]
			add
			{
				PluginEvent pluginEvent = pluginEvent_7;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Combine(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_7, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
			[CompilerGenerated]
			remove
			{
				PluginEvent pluginEvent = pluginEvent_7;
				PluginEvent pluginEvent2;
				do
				{
					pluginEvent2 = pluginEvent;
					PluginEvent value2 = (PluginEvent)Delegate.Remove(pluginEvent2, value);
					pluginEvent = Interlocked.CompareExchange(ref pluginEvent_7, value2, pluginEvent2);
				}
				while ((object)pluginEvent != pluginEvent2);
			}
		}

		public static bool Load()
		{
			try
			{
				string pluginsPath = PluginsPath;
				if (BotManager.IsRunning)
				{
					throw new InvalidOperationException("Cannot Load plugins while the bot is running.");
				}
				if (Plugins != null)
				{
					ilog_0.ErrorFormat("[Load] This function can only be called once.");
					return false;
				}
				if (!Directory.Exists(pluginsPath))
				{
					Directory.CreateDirectory(pluginsPath);
				}
				AssemblyLoader<IPlugin> assemblyLoader = new AssemblyLoader<IPlugin>(pluginsPath, detectFileChanges: false);
				Plugins = new List<IPlugin>();
				foreach (IPlugin item in assemblyLoader.Instances.AsReadOnly())
				{
					try
					{
						Utility.smethod_0(item);
						item.Initialize();
						Plugins.Add(item);
					}
					catch (Exception exception)
					{
						ilog_0.Debug("[Load] Exception thrown when initializing " + item.Name + ". Plugin will not be loaded.", exception);
						Utility.smethod_1(item);
						item.Deinitialize();
					}
				}
				return true;
			}
			catch (Exception arg)
			{
				ilog_0.ErrorFormat("[Load] An exception occurred: {0}.", arg);
			}
			return false;
		}

		public static void Start()
		{
			foreach (IPlugin plugin in Plugins)
			{
				if (plugin.IsEnabled)
				{
					smethod_0(plugin);
				}
			}
		}

		private static void smethod_0(IPlugin iplugin_0)
		{
			smethod_3(iplugin_0, pluginEvent_0);
			try
			{
				iplugin_0.Start();
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during plugin Start.", exception);
			}
			smethod_3(iplugin_0, pluginEvent_1);
		}

		public static void Tick()
		{
			foreach (IPlugin plugin in Plugins)
			{
				if (plugin.IsEnabled)
				{
					smethod_1(plugin);
				}
			}
		}

		private static void smethod_1(IPlugin iplugin_0)
		{
			smethod_3(iplugin_0, pluginEvent_2);
			try
			{
				iplugin_0.Tick();
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during plugin Tick.", exception);
			}
			smethod_3(iplugin_0, pluginEvent_3);
		}

		public static void Stop()
		{
			foreach (IPlugin plugin in Plugins)
			{
				if (plugin.IsEnabled)
				{
					smethod_2(plugin);
				}
			}
		}

		private static void smethod_2(IPlugin iplugin_0)
		{
			smethod_3(iplugin_0, pluginEvent_4);
			try
			{
				iplugin_0.Stop();
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during plugin Stop.", exception);
			}
			smethod_3(iplugin_0, pluginEvent_5);
		}

		public static void Enable(IPlugin plugin)
		{
			if (BotManager.IsRunning)
			{
				throw new InvalidOperationException("Cannot Enable plugins while the bot is running.");
			}
			try
			{
				if (!plugin.IsEnabled)
				{
					plugin.Enable();
					smethod_3(plugin, pluginEvent_6);
				}
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during plugin Enable.", exception);
			}
		}

		public static void Disable(IPlugin plugin)
		{
			try
			{
				if (BotManager.IsRunning)
				{
					throw new InvalidOperationException("Cannot Disable plugins while the bot is running.");
				}
				if (plugin.IsEnabled)
				{
					plugin.Disable();
					smethod_3(plugin, pluginEvent_7);
				}
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during plugin Disable.", exception);
			}
		}

		private static void smethod_3(IPlugin iplugin_0, PluginEvent pluginEvent_8)
		{
			if (pluginEvent_8 != null)
			{
				try
				{
					pluginEvent_8(iplugin_0);
				}
				catch (Exception exception)
				{
					ilog_0.Error("[Invoke] Error during execution:", exception);
				}
			}
		}

		public static void Deinitialize()
		{
			if (Plugins == null)
			{
				return;
			}
			foreach (IPlugin plugin in Plugins)
			{
				try
				{
					plugin.Deinitialize();
				}
				catch (Exception arg)
				{
					ilog_0.ErrorFormat("[PluginManager] An exception occurred in {0}'s Deinitialize function. {1}", plugin.Name, arg);
				}
			}
			Plugins.Clear();
		}
	}
}
